package com.ybox.auth.service;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.ybox.auth.form.RegisterBody;
import com.ybox.auth.mapper.RegisterBody2SysUserMapper;
import com.ybox.common.core.constant.CacheConstants;
import com.ybox.common.core.text.Convert;
import com.ybox.common.core.utils.DateUtils;
import com.ybox.common.core.utils.ip.IpUtils;
import com.ybox.common.core.utils.uuid.IdUtils;
import com.ybox.common.core.web.domain.AjaxResult;
import com.ybox.common.email.domain.Email;
import com.ybox.common.email.service.MailService;
import com.ybox.common.redis.service.RedisService;
import com.ybox.system.api.model.LoginUser;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ybox.common.core.constant.Constants;
import com.ybox.common.core.constant.SecurityConstants;
import com.ybox.common.core.domain.R;
import com.ybox.common.core.enums.UserStatus;
import com.ybox.common.core.exception.ServiceException;
import com.ybox.common.core.utils.StringUtils;
import com.ybox.common.security.utils.SecurityUtils;
import com.ybox.system.api.service.RemoteSysUserService;
import com.ybox.system.api.domain.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 登录校验方法
 *
 * @author ych
 */
@Service
public class LoginService {
    @Autowired
    private RemoteSysUserService remoteSysUserService;
    @Autowired
    private SysPasswordService passwordService;
    @Autowired
    private SysRecordLogService recordLogService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private MailService mailService;

    @Autowired
    private Configuration configuration;

    private static final Logger log = LoggerFactory.getLogger(LoginService.class);

    @Value("${spring.mail.username}")
    // @NacosValue(value = "${name.username}", autoRefreshed = true)
    public String sendEmail;

    /**
     * 登录
     */
    public LoginUser login(String username, String password) {
        // 查询用户信息
        R<LoginUser> userResult = remoteSysUserService.getUserInfo(username, SecurityConstants.INNER);

        if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
            throw new ServiceException("登录用户：" + username + " 不存在");
        }

        // IP黑名单校验
        String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾，访问IP已被列入系统黑名单");
            throw new ServiceException("很遗憾，访问IP已被列入系统黑名单");
        }

        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }

        LoginUser userInfo = userResult.getData();
        SysUser user = userResult.getData().getSysUser();
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起，您的账号已被删除");
            throw new ServiceException("对不起，您的账号：" + username + " 已被删除");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用，请联系管理员");
            throw new ServiceException("对不起，您的账号：" + username + " 已停用");
        }
        passwordService.validate(user, password);
        recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
        return userInfo;
    }

    /**
     * 手机号登录
     *
     * @param username
     * @return
     */
    public LoginUser loginByPhone(String username) {
        // 查询用户信息
        R<LoginUser> userResult = remoteSysUserService.getUserInfo(username, SecurityConstants.INNER);
        LoginUser userInfo = null;

        if (R.FAIL == userResult.getCode() && "用户名或密码错误".equals(userResult.getMsg())) {
            return userInfo;
        }

        if (StringUtils.isNotNull(userResult.getData())) {
            userInfo = userResult.getData();
            SysUser user = userResult.getData().getSysUser();
            if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
                recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起，您的账号已被删除");
                throw new ServiceException("对不起，您的账号：" + username + " 已被删除");
            }
            if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
                recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用，请联系管理员");
                throw new ServiceException("对不起，您的账号：" + username + " 已停用");
            }
            recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");

        }
        return userInfo;
    }


    public void logout(String loginName) {
        recordLogService.recordLogininfor(loginName, Constants.LOGOUT, "退出成功");
    }

    /**
     * 注册
     */
    public SysUser register(RegisterBody registerBody) {
        // 用户名或密码为空 错误
        if (StringUtils.isNotEmpty(registerBody.getPassword()) && StringUtils.isNotEmpty(registerBody.getConfirmPassword())
                && !registerBody.getPassword().equals(registerBody.getConfirmPassword())) {
            throw new ServiceException("输入密码不一致！");
        }
        // 注册用户信息
        SysUser sysUser = new SysUser();
        // registerBody字段自动映射到sysUser
        sysUser = RegisterBody2SysUserMapper.INSTANCE.toSysUser(registerBody);
        sysUser.setNickName("Ybox" + System.currentTimeMillis());
        // 如果用户名和密码为空，说明是手机号注册，将手机号设置为用户名
        if (null == registerBody.getUsername() && null == registerBody.getPassword()) {
            sysUser.setUserName(registerBody.getPhone());
            sysUser.setPhonenumber(registerBody.getPhone());
        } else {
            // 不是手机号注册的时候要设置密码（邮箱注册）
            sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
            // 设置停用状态，用户点击激活后设置正常
            sysUser.setStatus(UserStatus.DISABLE.getCode());
            sysUser.setEmail(registerBody.getUsername());
        }
        R<?> registerResult = remoteSysUserService.registerUserInfo(sysUser, SecurityConstants.INNER);

        if (R.FAIL == registerResult.getCode()) {
            throw new ServiceException(registerResult.getMsg());
        }
        recordLogService.recordLogininfor(registerBody.getUsername(), Constants.REGISTER, "注册成功");
        return sysUser;
    }

    /**
     * 发送激活邮箱
     *
     * @param receiverEmail
     * @return
     */
    public AjaxResult sendActiveCode(String receiverEmail) {
        // 1.构建发送邮件参数
        Email email = new Email();
        email.setSenderEmail(sendEmail);
        email.setReceiverEmail(receiverEmail);
        email.setSubject("感谢您使用YBox,确认电子邮件来注册");
        email.setHtml(true);
        email.setSentDate(new Date());

        // 2.构建邮件模板
        // 有效时间 1天后过期
        String time = DateUtils.parseDateToStr(DateUtils.DATE_TIME_FORMAT, DateUtils.addDay(new Date(), 1));
        // UUID
        String uuid = IdUtils.fastSimpleUUID();

        Map<String, String> map = new HashMap<>(2);
        map.put("url", "http://localhost:9200/active?email=" + receiverEmail + "&uuid=" + uuid);
        map.put("reserve", receiverEmail);
        map.put("time", time);

        // 3.邮件内容通过freemarker生成html文件
        StringWriter out = new StringWriter();
        Map<String, Object> params = new HashMap<>();
        try {
            Template template = configuration.getTemplate("email.ftl");
            params.put("content", new JSONObject(map));
            template.process(params, out);
        } catch (freemarker.template.TemplateException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        String content = out.toString();
        email.setContent(content);
        // 4.发送邮件
        mailService.sendMail(email);
        try {
            // 5.保存到redis
            redisService.setCacheObject(receiverEmail, uuid, 1L, TimeUnit.DAYS);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("发送激活游戏验证码失败,发送到邮箱：{},发送内容：{},错误{}", receiverEmail, content, e.getMessage());
            return AjaxResult.error("发送激活游戏验证码失败！");
        }
        return AjaxResult.success(uuid);
    }

    /**
     * 激活邮箱
     *
     * @param receiverEmail
     * @param uuid
     * @return
     */
    public Boolean activeEmail(String receiverEmail, String uuid) {
        redisService.setCacheObject(receiverEmail, uuid, 1L, TimeUnit.DAYS);
        Object cacheObject = redisService.getCacheObject(receiverEmail);
        if (null == cacheObject) {
            return false;
        }
        // 1.删除redis缓存
        redisService.deleteObject(receiverEmail);
        // 2.查询用户信息
        R<LoginUser> userResult = remoteSysUserService.getUserInfo(receiverEmail, SecurityConstants.INNER);
        if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
            recordLogService.recordLogininfor(receiverEmail, Constants.LOGIN_FAIL, "登录用户不存在");
            throw new ServiceException("登录用户：" + receiverEmail + " 不存在");
        }
        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }
        // 3.构建用户信息
        SysUser user = userResult.getData().getSysUser();
        user.setStatus(UserStatus.OK.getCode());
        // 2.更新用户状态
        R<Boolean> booleanR = remoteSysUserService.updateUserInfo(user, SecurityConstants.INNER);
        return booleanR.getData();
    }
}
